package com.mic.yzzn.plc.common.control.datastructure;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.UUID;

import com.mic.yzzn.plc.common.ins.datastructure.PLCContactorNumber;
import com.mic.yzzn.plc.common.ins.datastructure.PLCDataRegisterNumber;
import com.mic.yzzn.plc.common.instructions.basic.PLCRequestInstruction;
import com.mic.yzzn.plc.common.instructions.basic.PLCResponseInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCDataRegisterReadInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCDataRegisterWriteInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCMultipleContactorReadInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCMultipleContactorWriteInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCSingleContactorReadInstruction;
import com.mic.yzzn.plc.common.instructions.request.PLCSingleContactorWriteInstruction;
import com.mic.yzzn.plc.common.instructions.response.PLCDataRegisterReadResponse;
import com.mic.yzzn.plc.common.instructions.response.PLCMultipleReadResponse;
import com.mic.yzzn.plc.common.instructions.response.PLCSingleReadResponseInstruction;
import com.mic.yzzn.plc.common.toolUtils.PLCContactorCode;
import com.mic.yzzn.plc.common.toolUtils.PLCDataCode;
import com.mic.yzzn.plc.common.ins.datastructure.PLCInstructionTuple;


public class PLCMissionResult implements Serializable
{
	/** 任务结果类型 */
	public static final int PLCResultTypeSucceed = 0,
			PLCResultTypeNetWorkFail = 1,
			PLCResultTypeCollectorBusyFail = 2,
			PLCResultTypeCollectorAsleep = 3,
			PLCResultTypeMissionInsertError = 4,
			PLCResultMissionPriorityError = 5;

	/** 序列化版本号 */
	private static final long serialVersionUID = -1392507672646289075L;
	/** 结果的UUID */
	private UUID resultID;
	/** 任务的数据结果 */
	private ArrayList<PLCData> resultData = new ArrayList<PLCData>();
	/** 结果的类型 */
	private int resultType;
	
	@SuppressWarnings("unused")
	private PLCMissionResult()
	{
		
	}
	
	public PLCMissionResult(UUID resultID)
	{
		this.resultID =resultID;
	}

	public PLCMissionResult(UUID resultID, ArrayList<PLCData> datas)
	{
		this.resultID =resultID;
		this.resultData = datas;
	}

	
	// 不同类型的返回指令的处理方法
	private void handleDataRegisterReadResponse(PLCInstructionTuple tuple)
	{
		// 取出指令
		PLCDataRegisterReadResponse response = new PLCDataRegisterReadResponse();
		PLCDataRegisterReadInstruction request = 
				(PLCDataRegisterReadInstruction) tuple.requestInstruction;
		response.initWithString(tuple.responseString);
		
		// 判断响应类型
		boolean isWrong = response.getInstructionTypeCode().equals(PLCResponseInstruction.PLCInstructionTypeErrorResponseCode);
		
		// 遍历返回数据
		PLCDataRegisterNumber rNumber = request.getDataRegisterNumber();
		int intNumber = Integer.parseInt(rNumber.getBeginBCDDataNumber());
		for (int i = 0;i < rNumber.range(); ++i)
		{
			// 取出寄存器编号
			String dataNumber = String.valueOf(intNumber);
			// 取出数据
			String data = (isWrong)? response.getInstructionTypeCode(): PLCDataRegisterReadResponse.getRealDataRegisterData(response.getResponseData().get(i));

			// 初始化PLC数据
			PLCData plcData = new PLCData();
			plcData.setDataNumber(dataNumber);
			plcData.setData(data);
			plcData.setInstruction(request.getInstructionString());
			plcData.setInstructionCode(request.getRequestCode());
			plcData.setState(tuple.responseState);
			
			// 将数据添加到数组中
			this.resultData.add(plcData);
			
			// 递增地址
			++intNumber;
		}
	}
	
	private void handleMultipleContactorReadResponse(PLCInstructionTuple tuple)
	{
		// 取出指令
		PLCMultipleReadResponse response = new PLCMultipleReadResponse();
		PLCMultipleContactorReadInstruction request =
				(PLCMultipleContactorReadInstruction) tuple.requestInstruction;
		response.initWithString(tuple.responseString);
		
		// 判断响应类型
		boolean isWrong = response.getInstructionTypeCode().equals(PLCResponseInstruction.PLCInstructionTypeErrorResponseCode);
		
		// 遍历返回数据
		for (int i = 0; i < request.getContactorNumbers().size(); ++i)
		{
			// 取出触点编号
			String dataNumber = request.getContactorNumbers().get(i).toString();
			// 取出数据
			String data = (isWrong)? response.getInstructionTypeCode() : response.getResponseData().get(i);
			
			// 初始化PLC数据
			PLCData plcData = new PLCData();
			plcData.setDataNumber(dataNumber);
			plcData.setData(data);
			plcData.setInstruction(request.getInstructionString());
			plcData.setInstructionCode(request.getRequestCode());
			plcData.setState(tuple.responseState);
			
			// 将数据添加到数组中
			this.resultData.add(plcData);
		}
	}
	
	private void handleSingleContactorReadResponse(PLCInstructionTuple tuple)
	{
		// 取出指令
		PLCSingleReadResponseInstruction response = new PLCSingleReadResponseInstruction();
		PLCSingleContactorReadInstruction request = 
				(PLCSingleContactorReadInstruction) tuple.requestInstruction;
		response.initWithString(tuple.responseString);
		
		// 取出触点编号
		String dataNumber = request.getContactorNumber().toString();
		String data;
		// 判断响应类型
		if (response.getInstructionTypeCode().equals(PLCResponseInstruction.PLCInstructionTypeErrorResponseCode))
		{
			data = response.getInstructionTypeCode();
		}
		else // 响应正常
		{
			data = response.getContactorData();
		}

		// 初始化PLC数据
		PLCData plcData = new PLCData();
		plcData.setDataNumber(dataNumber);
		plcData.setData(data);
		plcData.setInstruction(request.getInstructionString());
		plcData.setInstructionCode(request.getRequestCode());
		plcData.setState(tuple.responseState);
		
		// 将数据添加到数组中
		this.resultData.add(plcData);
	}
	
	private void handleDataRegisterWriteResponse(PLCInstructionTuple tuple)
	{
		// 取出指令
		PLCResponseInstruction response = new PLCResponseInstruction();
		PLCDataRegisterWriteInstruction request = 
				(PLCDataRegisterWriteInstruction) tuple.requestInstruction;
		response.initWithString(tuple.responseString);
		
		// 取出寄存器编号
		PLCDataRegisterNumber rNumber = request.getDataRegisterNumber();
		// 取出写入结果
		String data = response.getInstructionTypeCode();

		// 初始化PLC数据
		PLCData plcData = new PLCData();
		plcData.setDataNumber(rNumber.toString());
		plcData.setData(data);
		plcData.setInstruction(request.getInstructionString());
		plcData.setInstructionCode(request.getRequestCode());
		plcData.setState(tuple.responseState);
		
		// 将数据添加到数组中
		this.resultData.add(plcData);
	}
	
	private void handleMultipleContactorWriteResponse(PLCInstructionTuple tuple)
	{
		// 取出指令
		PLCResponseInstruction response = new PLCResponseInstruction();
		PLCMultipleContactorWriteInstruction request = 
				(PLCMultipleContactorWriteInstruction) tuple.requestInstruction;
		response.initWithString(tuple.responseString);
		
		// 取出触点编号
		for (PLCContactorNumber contactorNumber : request.getContactorNumbers())
		{
			// 取出触点编号
			String dataNumber = contactorNumber.toString();
			// 取出写入结果
			String data = response.getInstructionTypeCode();
			
			// 初始化PLC数据
			PLCData plcData = new PLCData();
			plcData.setDataNumber(dataNumber);
			plcData.setData(data);
			plcData.setInstruction(request.getInstructionString());
			plcData.setInstructionCode(request.getRequestCode());
			plcData.setState(tuple.responseState);
			
			// 将数据添加到数组中
			this.resultData.add(plcData);
		}
	}
	
	private void handleSingleContactorWriteResponse(PLCInstructionTuple tuple)
	{
		// 取出指令
		PLCResponseInstruction response = new PLCResponseInstruction();
		PLCSingleContactorWriteInstruction request = 
				(PLCSingleContactorWriteInstruction) tuple.requestInstruction;
		response.initWithString(tuple.responseString);
		
		// 取出触点编号
		String dataNumber = request.getContactorNumber().toString();
		// 取出写入结果
		String data = response.getInstructionTypeCode();
		
		// 初始化PLC数据
		PLCData plcData = new PLCData();
		plcData.setDataNumber(dataNumber);
		plcData.setData(data);
		plcData.setInstruction(request.getInstructionString());
		plcData.setInstructionCode(request.getRequestCode());
		plcData.setState(tuple.responseState);
		
		// 将数据添加到数组中
		this.resultData.add(plcData);
	}
	
	/**
	 * 通过指令对初始化
	 * @param responseInstructions 指令对数组
	 */
	public void initWithResponseInstruction(ArrayList<PLCInstructionTuple> responseInstructions)
	{
		// 设置结果类型
		this.resultType = PLCMissionResult.PLCResultTypeSucceed;
		
		// 遍历每一个tuple
		for (PLCInstructionTuple tuple : responseInstructions)
		{
			PLCRequestInstruction requestInstruction = tuple.requestInstruction;

			if (requestInstruction instanceof PLCDataRegisterReadInstruction)
			{
				handleDataRegisterReadResponse(tuple);
			}
			else if (requestInstruction instanceof PLCMultipleContactorReadInstruction)
			{
				handleMultipleContactorReadResponse(tuple);
			}
			else if (requestInstruction instanceof PLCSingleContactorReadInstruction)
			{
				handleSingleContactorReadResponse(tuple);
			}
			else if (requestInstruction instanceof PLCDataRegisterWriteInstruction)
			{
				handleDataRegisterWriteResponse(tuple);
			}
			else if (requestInstruction instanceof PLCMultipleContactorWriteInstruction)
			{
				handleMultipleContactorWriteResponse(tuple);
			}
			else if (requestInstruction instanceof PLCSingleContactorWriteInstruction)
			{
				handleSingleContactorWriteResponse(tuple);
			}
		}
	}
	
	@Override
	public String toString()
	{
		StringBuffer buffer;
		buffer = new StringBuffer();

		buffer.append("ID: " + resultID.toString());
		buffer.append("\nresultType: " + resultType);
		for (PLCData data : resultData)
		{
			buffer.append("\n" + "dataNumber: " + data.getDataNumber() + " " + "data: " + data.getData() + " " + "state: " + data.getState());
		}
		
		return buffer.toString();
	}
	
	// Getter
	public UUID getResultID()
	{
		return resultID;
	}
	
	public ArrayList<PLCData> getResultData()
	{
		return resultData;
	}
	
	public int getResultType()
	{
		return resultType;
	}
	
	// Setter
	public void setResultType(int resultType)
	{
		this.resultType = resultType;
	}

	/**
	 * 检测是否已经完成任务(每一条指令都没有错误)
	 * @return 是否完成任务
     */
	public boolean isFinished()
	{
		for (PLCData data : resultData)
		{
			if (!data.isCorrect())
			{
				return false;
			}
		}

		return true;
	}
}

